/*
** pud_proc.c for libpud in mrcellophane/ftrace/src/libpud
** 
** Made by solomon hykes
** Login   <torgau@gmail.com>
** 
** Started on  Thu May 12 21:54:14 2005 solomon hykes
** Last update Mon May 16 18:54:31 2005 solomon hykes
*/

#include <errno.h>
#include <unistd.h>

#include "pud_sys.h"

static sys_pud_process	*new_process(pid_t pid)
{
  sys_pud_process	*proc;

  proc = malloc(sizeof(*proc));
  proc->pid = pid;
  proc->event_count = 0;
  if (kill(pid, 0) == -1)
    proc->status = status_dead;
  else
    proc->status = status_running;
  return (proc);
}

pud_process	*pud_attach(pid_t pid)
{
  while (ptrace(PT_ATTACH, pid, 0, 0) == -1)
    if (errno != EAGAIN)
      return (NULL);
  return ((pud_process *)new_process(pid));
}

t_ret		pud_trace_me()
{
  while (ptrace(PT_TRACE_ME, 0, 0, 0) == -1)
    if (errno != EAGAIN)
      return (ret_err);
  return (ret_ok);
}

extern char	**environ;

pud_process	*pud_launch(char *args[])
{
  pid_t		pid;

  pid = fork();
  if (pid == -1)
    return (NULL);
  if (pid == 0)
    {
      if (pud_trace_me() == ret_err)
	{
#ifdef DEBUG
	  fprintf(stderr, "pud_trace_me() failed: son exiting\n");
#endif
	  exit(126);
	}
      execve(args[0], args, environ);
#ifdef DEBUG
      perror("execve");
#endif
      exit(127);
    }
  else
    return ((pud_process *)new_process(pid));
}

t_ret		pud_detach(pud_process *p)
{
  sys_pud_process	*proc = (sys_pud_process *)p;

  while (ptrace(PT_DETACH, proc->pid, (caddr_t)1, 0) == -1)
    if (errno != EAGAIN)
      return (ret_err);
  return (ret_ok);
}
